<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
 <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.21">
 <TITLE>Linux netfilter Hacking HOWTO: Netfilter Hooks for Tunnel Writers</TITLE>
 <LINK HREF="netfilter-hacking-HOWTO-7.html" REL=next>
 <LINK HREF="netfilter-hacking-HOWTO-5.html" REL=previous>
 <LINK HREF="netfilter-hacking-HOWTO.html#toc6" REL=contents>
</HEAD>
<BODY>
<A HREF="netfilter-hacking-HOWTO-7.html">Next</A>
<A HREF="netfilter-hacking-HOWTO-5.html">Previous</A>
<A HREF="netfilter-hacking-HOWTO.html#toc6">Contents</A>
<HR>
<H2><A NAME="s6">6.</A> <A HREF="netfilter-hacking-HOWTO.html#toc6">Netfilter Hooks for Tunnel Writers</A></H2>

<P>Authors of tunnel (or encapsulation) drivers should follow two
simple rules for the 2.4 kernel (as do the drivers inside the kernel,
like net/ipv4/ipip.c):</P>
<P>
<UL>
<LI>Release skb->nfct if you're going to make the packet unrecognisable
(ie. decapsulating/encapsulating).  You don't need to do this if you
unwrap it into a *new* skb, but if you're going to do it in place, you
must do this.

<P>Otherwise: the NAT code will use the old connection tracking
information to mangle the packet, with bad consequences.</P>

</LI>
<LI>Make sure the encapsulated packets go through the LOCAL_OUT
hook, and decapsulated packets go through the PRE_ROUTING hook (most
tunnels use ip_rcv(), which does this for you).

<P>Otherwise: the user will not be able to filter as they expect to with
tunnels.</P>
</LI>
</UL>
</P>

<P>The canonical way to do the first is to insert code like the
following before you wrap or unwrap the packet:</P>
<P>
<BLOCKQUOTE><CODE>
<PRE>
        /* Tell the netfilter framework that this packet is not the
          same as the one before! */
#ifdef CONFIG_NETFILTER
        nf_conntrack_put(skb->nfct);
        skb->nfct = NULL;
#ifdef CONFIG_NETFILTER_DEBUG
        skb->nf_debug = 0;
#endif
#endif
</PRE>
</CODE></BLOCKQUOTE>
</P>

<P>Usually, all you need to do for the second, is to find where the
newly encapsulated packet goes into "ip_send()", and replace it with
something like:</P>
<P>
<BLOCKQUOTE><CODE>
<PRE>
        /* Send "new" packet from local host */
        NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, ip_send);
</PRE>
</CODE></BLOCKQUOTE>
</P>

<P> Following these rules means that the person setting up the packet
filtering rules on the tunnel box will see something like the
following sequence for a packet being tunnelled:</P>
<P>
<OL>
<LI> FORWARD hook: normal packet (from eth0 -> tunl0)</LI>
<LI> LOCAL_OUT hook: encapsulated packet (to eth1).</LI>
</OL>
</P>
<P>And for the reply packet:
<OL>
<LI> LOCAL_IN hook: encapsulated reply packet (from eth1)</LI>
<LI> FORWARD hook: reply packet (from eth1 -> eth0).</LI>
</OL>
</P>

<HR>
<A HREF="netfilter-hacking-HOWTO-7.html">Next</A>
<A HREF="netfilter-hacking-HOWTO-5.html">Previous</A>
<A HREF="netfilter-hacking-HOWTO.html#toc6">Contents</A>
</BODY>
</HTML>
